package com.atguigu.juc;

import java.util.concurrent.*;

/**
 * @author: 封捷
 * @create-date: 2022/8/29 10:17
 */
public class DemoCompletableFuture01 {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        // 1、创建自定义线程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                3,
                5,
                10,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(5));

        // 2、让 CompletableFuture 在不同线程中执行任务
        // runAsync() 方法：封装无返回值任务
        CompletableFuture.runAsync(()->{
            while (true) {
                try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {}
                System.out.println(Thread.currentThread().getName() + " is working");
            }
        }, executor);

        // supplyAsync() 方法：封装有返回值任务
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                }
                System.out.println(Thread.currentThread().getName() + " is working");
            }
            return "happy task result";
        }, executor);

        // 获取有返回值任务的返回结果方案一：调用 get() 方法。
        // 同步：在当前线程调用 get() 方法，如果对应的任务没有结束，get() 方法会把当前线程阻塞
        String taskResultGet = future.get();
        System.out.println("taskResultGet = " + taskResultGet);

        // 获取有返回值任务的返回结果方案二：基于异步回调
        // 异步：当前线程调用 whenComplete() 方法设定好异步回调之后，当前线程就可以继续做别的事情了，当前线程不会被阻塞
        // 什么时候目标任务有了返回值，什么时候在其它线程调用 BiConsumer 对象的 accept() 方法
        future.whenComplete((String taskResultWhen, Throwable throwable)->{
            System.out.println("taskResultWhen = " + taskResultWhen);
        });

    }

}
